<template>
    <div class="internationalization">
        <div
            class="code-box"
            v-for="(item, index) in data"
            :key="index">
            <t v-if="item.title" :id="item.id || ''" class="t2" v-html="item.title || ''"></t>
            <t v-if="item.subTitle" :id="item.id || item.subTitle || ''" v-html="item.subTitle || ''"></t>
            <template v-if="item.des">
                <li v-for="d in item.des" :key="d" v-html="d"></li>
            </template>
            <pre-code :code="item.code"></pre-code>
        </div>
        <div>
            <el-switch
                v-model="lang"
                active-value="en-US"
                inactive-value="zh-CN"
                active-text="英文"
                inactive-text="中文">
            </el-switch>
            <p>{{ $t('example1') }}</p>
            <p>{{ $t('example3', [666]) }}</p>
            <p>{{ $t('example4') }}</p>
            <p>{{ $t('example7') }}</p>

            <p>{{ message }}</p>
            <p>{{ computedMessage }}</p>
        </div>
        <el-backtop target=".main-container"></el-backtop>
    </div>
</template>

<script>
/* eslint-disable max-len */
import {
    ref, computed, inject, watch, onMounted, getCurrentInstance,
} from 'vue';
import { useStore } from 'vuex';
import { changeLang } from '../locale';

export default {
    setup() {
        const store = useStore();
        const instance = getCurrentInstance();
        let prototypeI18n;
        let i18nFallback;
        try {
            prototypeI18n = instance.appContext.config.globalProperties.$i18n;
            i18nFallback = instance.appContext.config.globalProperties.$t;
            // eslint-disable-next-line no-empty
        } catch (error) {}
        if (!prototypeI18n) prototypeI18n = inject('$i18n', {});
        const t = (prototypeI18n || {}).t || i18nFallback || ((s) => s);

        // 切换语言类型时，该文案不会自动切换语言
        const message = ref(t('example2', { msg: '再见嘞您！' }));
        // 需要使用 computed 计算属性，才能使下面的文案跟随语言类型的切换而切换
        const computedMessage = computed(() => t('example2', { msg: '再见吧！' }));
        const lang = ref(window.localStorage.getItem('lang') || 'zh-CN');
        watch(() => lang.value, (val) => changeLang(val));

        onMounted(() => { store.commit('updateArticleTree'); });

        return {
            message,
            computedMessage,
            lang,
            data: [
                {
                    title: '配置 I18n 多语言',
                    id: '配置 I18n 多语言',
                    des: [
                        '当你需要使用<span class="s-code">i18n</span>处理多语言时，你需要将<span class="s-code">sibionics-ui-next</span>内置的语言包一并导入',
                        '另外，需要注意的是，你还需要确保将<span class="s-code">i18n.global</span>挂载在<span class="s-code">Vue</span>的原型上，使用<span class="s-code">app.provide</span>注册为全局提供者，以保证组件内部的语言转换相关功能正常运行',
                    ],
                    code: // eslint-disable-next-line vue/script-indent
`import { createApp } from 'vue';
// 引入 element-plus
import ElementPlus from 'element-plus';
// 引入 element-plus 图标库
import * as ElementPlusIconsVue from '@element-plus/icons-vue';
// 引入 element-plus 样式
import 'element-plus/dist/index.css';
// 引入 sibionics-ui-next
import sibionics from 'sibionics-ui-next';
// 引入 sibionics-ui-next 样式文件
import 'sibionics-ui-next/lib/index.css';

import axios from 'axios';
import { i18n } from './locale/index';
import router from './router';
import App from './App';

const app = createApp(App);

/** 全局注册 axios 以保证组件内部的自动请求接口获取数据的相关功能正常运行 */
// 方式一：将 axios 注册为全局提供者，命名名称为 $axios
// app.provide('$axios', axios);
// 方式二：将 axios 挂载在 app 原型上，命名名称为 $axios
app.config.globalProperties.$axios = axios;


/** 全局注册 i18n 以保证组件内部的国际化相关功能正常运行 */
// 方式一：将 i18n.global 注册为全局提供者，命名名称为 $i18n
// app.provide('$i18n', i18n.global);
// 方式二：将 i18n.global 挂载在 app 原型上，命名名称为 $i18n
app.config.globalProperties.$i18n = i18n.global;

// 注册 ElementPlus 图标组件
Object.keys(ElementPlusIconsVue).forEach((key) => app.component(key, ElementPlusIconsVue[key]));

app.use(ElementPlus).use(i18n).use(sibionics).use(router).mount('#app');
`,
                },
                {
                    subTitle: './locale/index.js',
                    des: [
                        '本地需要安装<span class="s-code">vue-i18n@9</span>的版本',
                    ],
                    code: // eslint-disable-next-line vue/script-indent
`
// vue-i18n@9 版本
import { createI18n } from 'vue-i18n';

// element 内置语言包
import zhCNElement from 'element-plus/dist/locale/zh-cn.mjs'; // 中文简体
import zhTWElement from 'element-plus/dist/locale/zh-tw.mjs'; // 中文繁体-台湾
import enUSElement from 'element-plus/dist/locale/en.mjs'; // 英语
// sibionics-ui-next 内置语言包；目前仅支持 'zh-CN'、'zh-TW'、'zh-HK'、'en-US'
import zhCNSib from 'sibionics-ui-next/lib/locale/lang/zh-CN';
import zhTWSib from 'sibionics-ui-next/lib/locale/lang/zh-TW';
import enUSSib from 'sibionics-ui-next/lib/locale/lang/en-US';
// 本地语言包
import zhCNLocale from './lang/zh-CN';
import zhTWLocale from './lang/zh-TW';
import enUSLocale from './lang/en-US';
// 其他语言......

import store from '../store';

const languages = {
    'zh-CN': { ...zhCNElement, ...zhCNSib, ...zhCNLocale },
    'zh-TW': { ...zhTWElement, ...zhTWSib, ...zhTWLocale },
    'en-US': { ...enUSElement, ...enUSSib, ...enUSLocale },
};

export const i18n = createI18n({
    locale: store.state.language,
    fallbackLocale: 'zh-CN',
    messages: languages,
});

// 获取当前语言包，提供给 element-plus 切换语言使用
export const getLocales = (lang) => languages[lang];

// 切换当前语言类型方法封装
export const changeLang = (lang) => {
    if (!languages[lang]) {
        // eslint-disable-next-line
        console.warn(\`系统中暂未配置 \${lang} 语言\`);
        return;
    }
    // 通过 vuex 修改 element 组件内部语言类型
    store.commit('updateLanguage', lang);
    // 修改本地 i18n 多语言类型
    i18n.global.locale = lang;
};

// 获取当前语言类型方法封装
export const getCurrentLang = () => i18n.global.locale;

`,
                },
                {
                    subTitle: './store/index.js',
                    code: // eslint-disable-next-line vue/script-indent
`// 使用 vuex 状态管理器存储语言类型 language
import { createStore } from 'vuex';

export default createStore({
    state() {
        return {
            language: window.localStorage.getItem('lang') || 'zh-CN',
        };
    },
    mutations: {
        updateLanguage(state, lang) {
            state.language = lang;
            window.localStorage.setItem('lang', lang);
        },
    },
});
`,
                },
                {
                    subTitle: './App.vue',
                    des: [
                        '考虑到<span class="s-code">ElementPlus</span>处理多语言方式的差异，<span class="s-code">App.vue</span>需要使用到<span class="s-code">el-config-provider</span>标签，并动态导入语言包才能使<span class="s-code">ElementPlus</span>的多语言功能正常使用',
                        '因此我们使用到了状态管理器<span class="s-code">vuex</span>来存储全局语言变量',
                    ],
                    code: // eslint-disable-next-line vue/script-indent
`<template>
    <el-config-provider :locale="locale">
        <router-view></router-view>
    </el-config-provider>
</template>

<script>
import { computed } from 'vue';
import { useStore } from 'vuex';
import { getLocales } from './locale';

export default {
    setup() {
        const store = useStore();
        // 获取全局语言类型
        const currentLang = computed(() => store.state.language);
        // 动态获取 element-plus 的语言包
        const locale = computed(() => getLocales(currentLang.value));

        return { locale };
    },
};
<\/script>
`,
                },
                {
                    subTitle: '本地语言包配置示例',
                    code: // eslint-disable-next-line vue/script-indent
`// lang/zh-CN.js
export default {
    example1: '你好',
    example2: '{msg} 世界!',
    example3: '{0} 世界!',
    example4: "{'你好'} 世界!",
    example5: '我要统治',
    example6: '这个世界',
    example7: '@:example5 @:example6 !!!!'
};


// lang/en-US.js
export default {
    example1: 'hello',
    example2: '{msg} world!',
    example3: '{0} world!',
    example4: "{'hello'} world!",
    example5: 'I want to rule',
    example6: 'the world',
    example7: '@:example5 @:example6 !!!!'
};

// ......
`,
                },
                {
                    subTitle: '使用示例',
                    code: // eslint-disable-next-line vue/script-indent
`<template>
    <p>{{ $t('example1') }}</p>
    <p>{{ $t('example3', [666]) }}</p>
    <p>{{ $t('example4') }}</p>
    <p>{{ $t('example7') }}</p>

    <p>{{ message }}</p>
    <p>{{ computedMessage }}</p>
</template>

<script>
import { ref, inject, computed, watch } from 'vue';
import { changeLang } from '../locale/index';

export default {
    setup() {
        const i18n = inject('$i18n');
        const t = i18n.t || (s => s);

        // 切换语言类型时，该文案不会自动切换语言
        const message = ref(t('example2', { msg: '再见嘞您！' }));
        // 需要使用 computed 计算属性，才能使下面的文案跟随语言类型的切换而切换
        const computedMessage = computed(() => t('example2', { msg: '再见吧！' }));

        const lang = ref(window.localStorage.getItem('lang') || 'zh-CN');
        watch(() => lang.value, (val) => changeLang(val));

        return {
            lang,
            message,
            computedMessage,
        };
    },
}
<\/script>
`,
                },
            ],
        };
    },
};
</script>

<style lang="scss">

.internationalization {
  .code-box {
    padding: 15px 0;
  }
  pre {
    display: flex;
  }
}
</style>
